#!/usr/bin/env python
# -*- coding: utf-8 -*-
import subprocess
from common import L, BASEDIR, sysConfPath
import functools, os, psutil
from configparser import RawConfigParser
import yaml, pytest, jinja2
from selenium import webdriver
from selenium.common.exceptions import WebDriverException, SessionNotCreatedException
from common.myDriver import MyDriver
from win32api import GetSystemMetrics


def getPO(yml):
    """
    :param yml
    :return: {
                "Baidu" :  [
                    {
                        "search": {
                            "type": "id",
                            "value": "kw",
                            "time_out": 30
                        }
                    }
                ]
    }
    """
    _page_list = {}
    pages = parse(yml)
    for k, v in pages.items():
        locators = v['locators']
        l_names = []
        for l in locators:
            _l_info = {}
            name = l.pop('name')
            _l_info[name] = l
            l_names.append(_l_info)
        _page_list[k] = l_names
    return _page_list

def generatePythonFile(pages, content):
    L.debug(content)
    templateVars = {
        'content': content
    }
    template = getTemplate('template.temp')
    pages = os.path.join(BASEDIR, pages)
    with open(pages, 'w', encoding='utf-8') as f:
        f.write(template.render(templateVars))

def getTemplate(template):
    template_loader = jinja2.FileSystemLoader(
        searchpath=os.path.join(sysConfPath, 'template'))
    template_env = jinja2.Environment(loader=template_loader)
    return template_env.get_template(template)

def endWith(*endStr):
    ends = endStr
    def __(s: str):
        f = map(s.endswith, ends)
        if True in f:
            return s
    return __

def loadYaml(yml):
    with open(yml, 'r', encoding='utf-8') as f:
        content = yaml.safe_load_all(f)
        for c in content:
            yield c

def parse(yml_dir, needList=False):
    L.info('parse yml path:' + yml_dir)
    if needList:
        yml2Pythons = []
    else:
        yml2Pythons = {}
    if os.path.isdir(yml_dir):
        for root, dirs, files in os.walk(yml_dir):
            for name in filter(endWith('yml'), files):
                watchFile = os.path.join(root, name)
                for c in loadYaml(watchFile):
                    yml2Pythons.append(c) if needList else yml2Pythons.update(c)
    else:
        for c in loadYaml(yml_dir):
            yml2Pythons.append(c) if needList else yml2Pythons.update(c)
    return yml2Pythons

def DDT(yml= None) -> list:
    caseList = parse(os.path.join(BASEDIR, yml), True)
    tagstr = getEnv('tag')
    tag = tagstr.split(',') if tagstr else []
    if tag:
        filterCase = []
        tag = [x.strip() for x in tag]
        for case in caseList:
            ctag = case.get('tag', None)
            if ctag:
                if list(set(ctag).intersection(set(tag))):
                    filterCase.append(case)
                else:
                    continue
        return filterCase
    else:
        return caseList

def shell(cmd):
    """
    执行系统命令,且跨平台
    """
    output, errors = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
    return output.decode('utf-8')

def singleton(cls):
    instance = {}

    @functools.wraps(cls)
    def _wrapper(*arg, **kw):
        if cls not in instance:
            instance[cls] = cls(*arg, **kw)
        return instance[cls]

    return _wrapper

def get_ini(file):
    _ini = RawConfigParser()
    _ini.read(file, encoding='utf-8')
    return _ini

def load_env(file):
    """读取.env文件(环境变量)"""
    file = os.path.join(BASEDIR, file)
    if not os.path.isfile(file):
        msg = 'Can not find env file "{}"'.format(file)
        return 1, msg
    msg = 'Loading env variables from  "{}"'.format(file)
    env_var = {}
    with open(file, 'r', encoding='utf-8') as f:
        for line in f:
            if "=" in line:
                var, value = line.split('=', 1)
            elif ":" in line:
                var, value = line.split(":", 1)
            else:
                raise BaseException('.env format error')
            env_var[var.strip()] = value.strip()
    return env_var, msg

def setEnv(**kw):
    for k,v in kw.items():
        os.environ[k] = v

def getEnv(var):
    try:
        return os.environ[var]
    except KeyError as e:
        return 0

def create_driver(driverPath, options):
    for i in range(3):
        try:
            __d = webdriver.Chrome(executable_path=driverPath, options= options)
            break
        except SessionNotCreatedException as e:
            L.error(e)
            pytest.exit('Version issue', -1)
        except WebDriverException as e:
            L.warning(e)
            proc_name= os.path.basename(driverPath).split('.')[0]
            for proc in psutil.process_iter():
                if proc.name() == proc_name:
                    proc.kill()
    return __d

@singleton
def get_driver(driverType= 'chromedriver.exe'):
    _dPath = os.path.join(BASEDIR, 'driver', driverType)
    if os.path.exists(_dPath):
        L.info('user {}'.format(_dPath))
    else:
        pytest.exit("Can't find '{}' in driver directory".format(driverType), -1)

    if getEnv('mode') == 'on':
        from selenium.webdriver.chrome.options import Options
        options = Options()
        options.add_argument('--no-sandbox')
        options.add_argument('--headless')
        options.add_argument('--disable-dev-shm-usage')
        options.add_argument('--disable-gpu')
        options.add_argument('--disable-features=NetworkService')
        options.add_argument("--disable-features=VizDisplayCompositor")
        # info=0,warn=1,error=2,fatal=4
        options.add_argument('log-level=3')
        options.add_argument('--window-size=%d,%d' %
                             (GetSystemMetrics(0), GetSystemMetrics(1)))
    else:
        options= None

    __d = create_driver(_dPath, options)
    return MyDriver(__d)


if __name__ == '__main__':
    var, msg = load_env('dev.env')
    L.info(var)
    L.info(msg)
